package ro.toporjinschi.androidorm;

import java.lang.reflect.InvocationTargetException;

import android.content.Context;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Pair;

public final class ORMLayer {
    private static final String ORM_DATABASE_NAME = "orm.database.name";
    private static final String ORM_DATABASE_VERSION = "orm.database.version";
    private static ORMLayer instance;
    private SQLiteOpenHelper sqLiteOpenHelper;

    private ORMLayer() {
    }

    public static ORMLayer getInstance() {
        if (instance == null) {
            throw new RuntimeException("DBSQLHelper is not initialized, Did you call DBSQLHelper.initialize?");
        }
        return instance;
    }

    public static void initialize(Context context, Class<? extends SQLiteOpenHelper> helper) {
        instance = new ORMLayer();
        final Pair<String, Integer> dbInfo = getDBInfo(context);
        instance.sqLiteOpenHelper = buildHelper(context, helper, dbInfo);
    }

    private static SQLiteOpenHelper buildHelper(Context context, Class<? extends SQLiteOpenHelper> clazz, Pair<String, Integer> dbInfo) {
        try {
            return clazz.getConstructor(Context.class, String.class, Integer.TYPE).newInstance(context, dbInfo.first, dbInfo.second);
        } catch (final IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (final InstantiationException e) {
            throw new RuntimeException(e);
        } catch (final IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (final InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (final NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    private static Pair<String, Integer> getDBInfo(Context context) {
        Pair<String, Integer> dbInfo = null;
        try {
            final Bundle metaData = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA).metaData;
            dbInfo = new Pair<String, Integer>(metaData.getString(ORM_DATABASE_NAME), metaData.getInt(ORM_DATABASE_VERSION));
        } catch (final Exception e) {
            final StringBuilder sb = new StringBuilder("ORM database configuration not found; Set the properties ");
            sb.append(ORM_DATABASE_NAME).append("&").append(ORM_DATABASE_VERSION);
            sb.append(" in your app manifest");
            throw new IllegalStateException(sb.toString(), e);
        }
        return dbInfo;
    }

    public SQLiteOpenHelper getSqLiteOpenHelper() {
        return this.sqLiteOpenHelper;
    }

    public SQLiteDatabase getReadableDatabase() {
        return this.sqLiteOpenHelper.getReadableDatabase();
    }

    public SQLiteDatabase getWritableDatabase() {
        return this.sqLiteOpenHelper.getWritableDatabase();
    }
}